1、 I2C 框架
	I2C 框架包括以下几个部分：
	1） I2C 核心；管理 I2C 适配器驱动和 I2C 设备驱动，此部分由linux提供
	2） I2C 适配器驱动；又叫 I2C 总线驱动，用于驱动 I2C 控制器，此部分由主控芯片厂家提供
	3） I2C 设备；又叫 I2C client ，用于描述 I2C 设备信息，一般在设备树中编写。
	4） I2C 设备驱动 ：又叫 i2c_driver ，用于驱动I2C设备，一移植厂家驱动或自己编写
	5） I2C-dev ；将 I2C 总线虚拟成字符设备，使应用层能直接访问 I2C 总线，由Linux系统提供
2、 I2C 适配器驱动
	对象 struct i2c_adapter 表示一个 I2C 适配器，其核心成员如下：
	//I2C 适配器操作函数集合
	const struct i2c_algorithm *algo;
	//适配器编号
	int nr;
	I2C 适配器驱动的核心就是完成对 struct i2c_adapter 的初始化，然后将其添加到系统中，如下是
向系统添加和删除 I2C 适配器驱动的函数
	//添加 I2C 适配器驱动，其中i2c_add_numbered_adapter需要静态指定编号
	int i2c_add_adapter(struct i2c_adapter *adapter)
	int i2c_add_numbered_adapter(struct i2c_adapter *adap)
	//删除 I2C 适配器驱动
	void i2c_del_adapter(struct i2c_adapter * adap)
3、 I2C 设备驱动
	I2C 设备驱动重点关注 i2c_client 和 i2c_driver ， i2c_client 描述的是 I2C 设备的信息，类
似于 platform 总线的 platform_device ， i2c_driver 描述的是 I2C 设备的驱动内容，类似于 plat
form 总线的 platform_driver；如下分别是 i2c_client 和 i2c_driver 对象的核心成员：
	struct i2c_client ：
		//从机地址
		unsigned short addr;
		//名称
		char name[I2C_NAME_SIZE];
		//对应的 I2C 适配器
		struct i2c_adapter *adapter;
		//继承的 device 对象
		struct device dev;
		//中断资源，iic匹配时会获取设备树描述的中断
		int irq;
	struct i2c_driver ：
		//设备和驱动匹配成功执行函数
		int (*probe)(struct i2c_client *, const struct i2c_device_id *);
			//设备或驱动匹配卸载执行函数
		int (*remove)(struct i2c_client *);
		//继承 device_driver
		struct device_driver driver;
		//传统的 ID 匹配表，即使使用设备树后此参数也不能为NULL
		const struct i2c_device_id *id_table;
	//注册 I2C 设备驱动
	i2c_add_driver(struct i2c_driver *driver)
	//注销 I2C 设备驱动
	void i2c_del_driver(struct i2c_driver *driver)
4、 I2C 设备和驱动匹配过程
	如下是 I2C 设备和驱动的匹配函数：
	static int i2c_device_match(struct device *dev, struct device_driver *drv)
	{
		struct i2c_client	*client = i2c_verify_client(dev);
		struct i2c_driver	*driver;

		/* 使用设备树进行匹配 */
		if (i2c_of_match_device(drv->of_match_table, client))
			return 1;
	
		/* 使用 ACPI 进行匹配 */
		if (acpi_driver_match_device(dev, drv))
			return 1;

		driver = to_i2c_driver(drv);
	
		/* 使用 id_table 进行匹配 */
		if (i2c_match_id(driver->id_table, client))
			return 1;

		return 0;
	}
5、 I2C 设备传输数据
	I2C 设备通过 i2c_transfer 可以完成数据的收发工作，函数原型如下：
	/**
	 * adap I2C 适配器
	 * msgs msg 列表
	 * num msg 数量
	 * 返回负值失败，返回其他非负值，发送的 msgs 数量
	 * 此函数在连续发送多个数据包时如果设置了I2C_M_NOSTART，在数据包直接不会等待ACK信号，可能会导致发送失败
	 */
	int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
6、 I2C 设备树
	在那条 I2C 总线下挂载设备就在那条总线的设备树节点下添加对应设备的子节点，节点命名规则 [标签:]名称[@地址]，
节点内容必须包含 reg 属性和 compatible 属性， reg 属性用于描述设备地址（设备地址采用7位地址法表示，合法地址范
围 0～127 ），compatible 属性用于设备和驱动的匹配，如下是在 i2c5 中添加一个 ap3216c 设备节点的示例。
	&i2c5 {
		//描述I2C控制器引脚，并使能I2C控制器
		pinctrl-names = "default", "sleep";
		pinctrl-0 = <&i2c5_pins_a>;
		pinctrl-1 = <&i2c5_pins_sleep_a>;
		status = "okay";

		//描述ap3216c设备
		ap3216c@1e {
			compatible = "alientek,ap3216c";
			reg = <0x1e>;
		};
	};

